<?php
// @formatter:off
/**
 * @file WCUser.php
 * @author Alejandro Dario Simi
 * @date $Date: 2013-06-22 17:58:11 +0000 (Sat, 22 Jun 2013) $
 *
 * $Id: WCUser.php 83 2013-06-22 17:58:11Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/tags/wcomix-1.0-BETA2/includes/representations/WCUser.php $
 */
// @formatter:on

/**
 * @class WCUser
 */
class WCUser extends WCTableRepresentation implements WCPreviews {
	/**
	 * Check WCTableRepresentation class documantation
	 * @var array
	 */
	protected $_PropertiesReadOnly = array(
		"id",
		"username",
		"password"
	);
	/**
	 * Check WCTableRepresentation class documantation
	 * @var array
	 */
	protected $_PropertiesBoolean = array(
		"web_access",
		"sys_access"
	);
	/**
	 * Check WCTableRepresentation class documantation
	 * @var array
	 */
	protected $_PropertiesPrefix = "usr_";
	/**
	 * Check WCTableRepresentation class documantation
	 * @var array
	 */
	protected $_PropertiesTable = "users";
	/**
	 * Check WCTableRepresentation class documantation
	 * @var array
	 */
	protected $_PropertiesNameColumn = "username";
	/**
	 *
	 * @var string
	 */
	protected $_profileCode = false;
	/**
	 * @var WCUserData
	 */
	protected $_data = null;

	public function __construct() {
		parent::__construct();
	}
	// Public methods.
	/**
	 * This method removes "awaiting activation" flags from database.
	 */
	public function activate() {
		//
		// Loading global pointers.
		global $wcDefaults;
		//
		// Checking that Read Only Mode is not activated.
		if(!$wcDefaults["read-only"]) {
			//
			// Creating a statement to update flags.
			// @{
			$stmt = null;
			$stmtId = __CLASS__."::".__FUNCTION__;
			if($this->_db->has($stmtId)) {
				$stmt = $this->_db->get($stmtId);
			} else {
				$query = "update  {$this->_dbprefix}users\n";
				$query .= "set     usr_hash_register = '',\n";
				$query .= "        usr_hash_dregister = '0'\n";
				$query .= "where   usr_id = :id";

				$stmt = $this->_db->prepare($stmtId, $query);
			}
			// @}
			//
			// Building database parameters.
			$params = array(":id" => $this->id());
			//
			// Updating flags in the database.
			$stmt->execute($params);
			//
			// Reloading representation to avoid issues.
			$this->reload();
		}
	}
	public function avatar() {
		$out = "";

		$this->loadData();
		if($this->_data) {
			$out = $this->_data->avatar();
		}

		return $out;
	}
	public function checkPassword($password) {
		/// @todo ver si esto se puede reemplazar por algo donde no tenga que pasar la
		/// password ya encriptada.
		return $this->password == $password;
	}
	public function & data() {
		$this->loadData();
		return $this->_data;
	}
	public function generatePreviews() {
		$out = false;

		return $out;
	}
	public function hasPreview() {
		return true;
	}
	public function hasPreviews() {
		return false;
	}
	public function loadByAuth($username, $password) {
		$this->clear();

		$ok = true;
		if(defined('WIKI_COMPATIBLE')) {
			$stmt = null;
			$stmtId = __CLASS__."::".__FUNCTION__."[1]";
			if($this->_db->has($stmtId)) {
				$stmt = $this->_db->get($stmtId);
			} else {
				$query = "select  *\n";
				$query .= "from    {$this->_dbprefix}users\n";
				$query .= "where   usr_username = :username";

				$stmt = $this->_db->prepare($stmtId, $query);
			}

			$params = array(":username" => $username);

			if($stmt->execute($params) && $stmt->rowCount() == 1) {
				$row = $stmt->fetch();
				$pass = explode(':', $row['usr_password']);
				if($pass[1] == 'B') {
					$password = ":B:{$pass[2]}:".md5("{$pass[2]}-{$password}");
				} elseif($pass[1] == 'A') {
					$password = ":A:{$pass[2]}";
				} else {
					$ok = false;
				}
			}
		}

		if($ok) {
			$stmt = null;
			$stmtId = __CLASS__."::".__FUNCTION__."[2]";
			if($this->_db->has($stmtId)) {
				$stmt = $this->_db->get($stmtId);
			} else {
				$query = "select  *\n";
				$query .= "from    {$this->_dbprefix}users\n";
				$query .= "where   usr_username = :username\n";
				$query .= " and    usr_password = :password";

				$stmt = $this->_db->prepare($stmtId, $query);
			}

			$params = array(
				":username" => $username,
				":password" => $password
			);
			if($stmt->execute($params) && $stmt->rowCount() == 1) {
				$row = $stmt->fetch();
				$this->load($row["usr_id"]);
			}
		}

		return $this->ok();
	}
	public function ok() {
		return parent::ok() && !$this->hash_register;
	}
	public function preview() {
		return $this->avatar();
	}
	public function previews() {
		return array();
	}
	public function profileCode(WCGroup &$group = null) {
		$this->loadProfileCode();

		$out = "ANON";

		if($group === null) {
			global $wcGroup;

			if($wcGroup) {
				$group = $wcGroup;
			} else {
				global $wcDefaults;
				global $wcGroupsHolder;

				$group = $wcGroupsHolder->groupById($wcDefaults['group']);
			}
		}

		if($group) {
			$out = $this->_profileCode[$group->id];
		}

		return $out;
	}
	/**
	 * This method allows to set password reset flags for the user.
	 *
	 * @return string Returns a hash string that can be used for further
	 * password validations. When error, returns false.
	 */
	public function resetPassword() {
		//
		// Loading global pointers.
		global $wcDefaults;
		//
		// Generating a random hash to be used as flag for password reset.
		$hash = "{$this->id()}|".md5(rand(1, 1000) * rand(1, 1000));
		//
		// Checking that Read Only Mode is not activated.
		if(!$wcDefaults["read-only"]) {
			//
			// Creating a statement to update password reset flags.
			// @{
			$stmt = null;
			$stmtId = __CLASS__."::".__FUNCTION__;
			if($this->_db->has($stmtId)) {
				$stmt = $this->_db->get($stmtId);
			} else {
				$query = "update  {$this->_dbprefix}users\n";
				$query .= "set     usr_hash_reset = :hash,\n";
				$query .= "        usr_hash_dreset = now()\n";
				$query .= "where   usr_id = :id";

				$stmt = $this->_db->prepare($stmtId, $query);
			}
			// @}
			//
			// Building database parameters.
			$params = array(
				":id" => $this->id(),
				":hash" => $hash
			);
			//
			// Attempting to update flags.
			if(!$stmt->execute($params) || $stmt->rowCount() != 1) {
				//
				// At this point, something went wrong, therefore
				// the hash to be return is false.
				$hash = false;
			}
		} else {
			//
			// On Read Only Mode, this hash is always false.
			$hash = false;
		}
		//
		// Returning generated hash.
		return $hash;
	}
	/**
	 * This method allows to get the users RSS hash for not-logged-in RSS
	 * downloads.
	 *
	 * @return string Returns a hash string that can be used for further
	 * RSS validations. On Read Only Method, if there's no hash for the
	 * current user it may return an empty string.
	 */
	public function rssHash() {
		//
		// Checking if there's a hash already generated.
		if(!$this->hash_rss) {
			//
			// Generating a RSS random hash string.
			$hash = "{$this->id()}|".md5(rand(1, 1000) * rand(1, 1000));
			//
			// Saving new hash in the database.
			$this->hash_rss = $hash;
		}
		//
		// Returning user RSS hash.
		return $this->hash_rss;
	}
	/**
	 * This method replaces current user password by another. It also clears
	 * reset password flags.
	 *
	 * @param string $password This is the new password to be set. If it has
	 * to be an encrypted string it must be encrypted before calling this
	 * method.
	 * @return boolean Returns true when the password was successfully
	 * changed.
	 */
	public function setPassword($password) {
		//
		// Loading global pointers.
		global $wcDefaults;
		//
		// Setting default value to be returned.
		$ok = true;
		//
		// Checking that:
		//	- Read Only Mode is not activated.
		//	- The current object has no issues.
		//	- And the property to be edited is not a read only property.
		if(!$wcDefaults["read-only"]) {
			//
			// Creating a statement to change password.
			// @{
			$stmt = null;
			$stmtId = __CLASS__."::".__FUNCTION__;
			if($this->_db->has($stmtId)) {
				$stmt = $this->_db->get($stmtId);
			} else {
				$query = "update  {$this->_dbprefix}users\n";
				$query .= "set     usr_password    = :password,\n";
				$query .= "        usr_hash_reset  = '',\n";
				$query .= "        usr_hash_dreset = 0\n";
				$query .= "where   usr_id = :id";

				$stmt = $this->_db->prepare($stmtId, $query);
			}
			// @}
			//
			// Building database parameters.
			$params = array(
				":id" => $this->id(),
				":password" => md5($password)
			);
			//
			// Attempting to update password in the database.
			if(!$stmt->execute($params) || $stmt->rowCount() != 1) {
				//
				// At this point something went wrong.
				$ok = false;
			}
			//
			// Reloading to avoid issues.
			$this->reload();
		}
		//
		// Returning modification status.
		return $ok;
	}
	public function sysAccess() {
		return $this->sys_access;
	}
	public function username() {
		return $this->username;
	}
	public function webAccess() {
		return $this->web_access;
	}
	// Protected methods.
	protected function clear() {
		$this->_info = array();
		$this->_ok = false;
	}
	public function loadProfileCode() {
		if(!$this->_profileCode) {
			global $wcGroupsHolder;

			$this->_profileCode = array();

			if(in_array($this->id, array(
				WC_USER_ROOT_ID,
				WC_USER_CRON_ID
			))) {
				foreach($wcGroupsHolder->groupIds() as $id) {
					$this->_profileCode[$id] = "ROOT";
				}
			} else {
				$stmt = null;
				$stmtId = __CLASS__."::".__FUNCTION__;
				if($this->_db->has($stmtId)) {
					$stmt = $this->_db->get($stmtId);
				} else {
					$query = "select  *\n";
					$query .= "from    {$this->_dbprefix}group_users\n";
					$query .= "where   rel_gu_user = :user";

					$stmt = $this->_db->prepare($stmtId, $query);
				}

				$params = array(":user" => $this->id);
				if($stmt->execute($params) && $stmt->rowCount() > 0) {
					foreach($stmt->fetchAll() as $row) {
						$this->_profileCode[$row["rel_gu_group"]] = $row["rel_gu_profile"];
					}
				}

				foreach($wcGroupsHolder->groups() as $group) {
					if(!isset($this->_profileCode[$group->id])) {
						$this->_profileCode[$group->id] = "ANON";
						$this->setDefaultProfile($group);
					}
				}
			}
		}
	}
	//
	// Protected methods.
	protected function loadData($firstTime = true) {
		if($this->_data === null) {
			global $wcUserDataHolder;

			$this->_data = $wcUserDataHolder->item($this->id);
			if(!$this->_data) {
				$wcUserDataHolder->create($this->id);

				$this->_data = null;
				if($firstTime) {
					$this->loadData(false);
				}
			}
		}
	}
	/**
	 * This method forces a user to have some sort of default privileges in a
	 * group.
	 *
	 * @note This method is not affected by Read Only Mode because it's needed
	 * to keep the system in good health.
	 *
	 * @param WCGroup $group Group where the default privileges must be set.
	 */
	protected function setDefaultProfile(WCGroup &$group) {
		//
		// Creating a statement to insert default privileges.
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "insert\n";
			$query .= "        into {$this->_dbprefix}group_users (\n";
			$query .= "              rel_gu_group, rel_gu_user, rel_gu_profile)";
			$query .= "        values(:group, :user, :profile)";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}
		//
		// Building database parameters.
		$params = array(
			":group" => $group->id,
			":user" => $this->id,
			":profile" => $group->isPublic() ? "USER" : "ANON"
		);
		//
		// Inserting privileges.
		$stmt->execute($params);
	}
}
?>
